﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;



namespace BookWriter
{
    public partial class Form1 : Form
    {
        public enum FileType
        {
            folder,
            txt,
            rtf
        }

        public class FileDesc
        {
            public TreeNode node;
            public TabPage page;
            public RichTextBox textBox;
            public string name;
            public string filename;
            public FileType type;
        }

        public string bookDir;
        public string bookName;
        public string title;
        public bool eventOn=true;


        HashSet<TabPage> contentChangeList = new HashSet<TabPage>();


        public Font contentFont;
        public Color contentFontColor;
        public Color contentColor;
        public bool isConfigChange;
        public Encoding bookEncoding;


        public Form1()
        {
            InitializeComponent();
            title = Text;
        }

        private void LoadDirNode(TreeNodeCollection parent,string dir)
        {
            List<String> files = new List<string>();

            var list = Directory.EnumerateDirectories(dir);
            foreach (var l in list)
                files.Add(l.Substring(dir.Length+1).ToLower());
            list = Directory.EnumerateFiles(dir , "*.txt");
            foreach (var l in list)
                files.Add(l.Substring(dir.Length + 1).ToLower());
            list = Directory.EnumerateFiles(dir, "*.rtf");
            foreach (var l in list)
                files.Add(l.Substring(dir.Length + 1).ToLower());

            parent.Clear();
            files.Sort();
            for (int i = 0; i < files.Count;i++ )
            {
                string name = files[i];
                FileType type;
                if (name.EndsWith(".txt"))
                {
                    name = name.Substring(0, name.Length - 4);
                    if (files.Contains(name))
                        continue;
                    type = FileType.txt;
                }
                else if (name.EndsWith(".rtf"))
                {
                    name = name.Substring(0, name.Length - 4);
                    if (files.Contains(name))
                        continue;
                    type = FileType.rtf;
                }
                else
                    type=FileType.folder;

                FileDesc fd=new FileDesc();
                fd.name = name;
                fd.type = type;
                fd.filename = dir + "\\" + fd.name;


                TreeNode node = new TreeNode();
                node.Text = fd.name;
                node.ImageKey = type.ToString();
                node.Tag = fd;

                fd.node = node;

                parent.Add(node);
                //如果存在子目录，更新
                string path = dir + "\\" + fd.name;
                if (Directory.Exists(path))
                    LoadDirNode(node.Nodes, path);
            }            
        }

        public void LoadDir(string dir)
        {
            bookDir = dir;
            bookName=Path.GetFileName(dir);
            Text = title + "-" +bookName;
            if (!Directory.Exists(bookDir + "\\content"))
                Directory.CreateDirectory(bookDir + "\\content");
            if (!Directory.Exists(bookDir + "\\material"))
                Directory.CreateDirectory(bookDir + "\\material");
            LoadDirNode(tv_charpter.Nodes, bookDir + "\\content");
            LoadDirNode(tv_material.Nodes, bookDir + "\\material");
            tab_dir.Enabled = true;
            tab_content.Enabled = true;
        }


        private void ｍ_open_Click(object sender, EventArgs e)
        {
            if(folderBrowserDialog1.ShowDialog()==DialogResult.OK)
            {
                LoadDir(folderBrowserDialog1.SelectedPath);
            }
        }

        private TreeNode addNode(TreeNodeCollection parent)
        {
            TreeNode node = new TreeNode();
            node.Text = "新节点";
            node.ImageKey = "txt";
            parent.Add(node);
            
            TreeNode pnode = node.Parent;
            FileDesc fd = new FileDesc();
            fd.name = node.Text;
            fd.type = FileType.folder;

            if(pnode!=null)
            { 
                FileDesc fd2=pnode.Tag as FileDesc;
                fd.filename = fd2.filename + "\\" + fd.name;
            }
            else
            {
                if (node.TreeView == tv_charpter)
                    fd.filename = bookDir + "\\content\\" + fd.name;
                else
                    fd.filename = bookDir + "\\material\\" + fd.name;
            }
            fd.node = node;
            node.Tag = fd;

            addContentPage(node);
            node.BeginEdit();
            return node;
        }

        private void m_dir_addsub_Click(object sender, EventArgs e)
        {
            if(tab_dir.TabIndex == 0)
            {
                if(tv_charpter.SelectedNode!=null)
                {
                    tv_charpter.SelectedNode =  addNode(tv_charpter.SelectedNode.Nodes);
                }
                else
                {
                    tv_charpter.SelectedNode =  addNode(tv_charpter.Nodes);
                }
            }
            else //if (tab_dir.TabIndex == 1)
            {
                if (tv_material.SelectedNode != null)
                {
                    tv_material.SelectedNode = addNode(tv_material.SelectedNode.Nodes);
                }
                else
                {
                    tv_material.SelectedNode = addNode(tv_material.Nodes);
                }
            }
        }

        private void m_dir_add_Click(object sender, EventArgs e)
        {
            if (tab_dir.TabIndex == 0)
            {
                if (tv_charpter.SelectedNode != null && tv_charpter.SelectedNode.Parent != null)
                {
                    tv_charpter.SelectedNode = addNode(tv_charpter.SelectedNode.Parent.Nodes);
                }
                else
                {
                    tv_charpter.SelectedNode = addNode(tv_charpter.Nodes);
                }
            }
            else //if (tab_dir.TabIndex == 1)
            {
                if (tv_material.SelectedNode !=null && tv_material.SelectedNode.Parent != null)
                {
                    tv_material.SelectedNode = addNode(tv_material.SelectedNode.Parent.Nodes);
                }
                else
                {
                    tv_material.SelectedNode = addNode(tv_material.Nodes);
                }
            }
        }

        private void addContentPage(TreeNode node)
        {
            TabPage page = new TabPage(node.Text);
            tab_content.TabPages.Add(page);
            RichTextBox tb = new RichTextBox();
            tb.MaxLength = int.MaxValue;
            tb.WordWrap = true;
            tb.ScrollBars = RichTextBoxScrollBars.Vertical;
            tb.Multiline = true;
            tb.AcceptsTab = true;
            tb.Font = contentFont;
            tb.BackColor = contentColor;
            page.Controls.Add(tb);
            tb.Dock = DockStyle.Fill;

            //MSWord.Application app = new MSWord.Application();

            FileDesc fd = node.Tag as FileDesc;
            fd.page = page;
            fd.textBox = tb;
            fd.textBox.Tag = fd;
            fd.textBox.TextChanged += onTextBoxChange;
            page.Tag = fd;

            if(File.Exists(fd.filename+".txt"))
            {
                eventOn = false;
                fd.textBox.Text = File.ReadAllText(fd.filename + ".txt",bookEncoding);
                eventOn = true;
            }
            else if (File.Exists(fd.filename + ".rtf"))
            {
                eventOn = false;
                fd.textBox.LoadFile(fd.filename + ".rtf");
                eventOn = true;
            }
            tab_content.SelectedTab = page;
        }

        private void tv_charpter_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            FileDesc fd = e.Node.Tag as FileDesc;
            if(fd.page!=null)
            {
                string new_text = e.Label ?? e.Node.Text;
                fd.page.Text = new_text + (contentChangeList.Contains(fd.page) ? "*" : "");
                new_text = fd.filename.Substring(0, fd.filename.Length - fd.name.Length) + new_text;
                if(fd.type==FileType.txt&&File.Exists(fd.filename+".txt"))
                {
                    File.Move(fd.filename+".txt",new_text+".txt");
                }
                else if (fd.type == FileType.rtf && File.Exists(fd.filename + ".rtf"))
                {
                    File.Move(fd.filename + ".rtf", new_text + ".rtf");
                }
                if(System.IO.Directory.Exists(fd.filename))
                {
                    Directory.Move(fd.filename,new_text);
                }
            }
        }

        private void m_font_Click(object sender, EventArgs e)
        {
            fontDialog1.Font = contentFont;
            if (fontDialog1.ShowDialog() == DialogResult.OK)
            {
                contentFont = fontDialog1.Font;
                refreshContentStyle();
                isConfigChange = true;
            }
        }

        private void m_bgcolor_Click(object sender, EventArgs e)
        {
            colorDialog1.Color = contentColor;
            if (colorDialog1.ShowDialog() == DialogResult.OK)
            {
                contentColor = colorDialog1.Color;
                refreshContentStyle();
                isConfigChange = true;
            }
        }


        private void m_fontcolor_Click(object sender, EventArgs e)
        {
            colorDialog1.Color = contentFontColor;
            if (colorDialog1.ShowDialog() == DialogResult.OK)
            {
                contentFontColor = colorDialog1.Color;
                refreshContentStyle();
                isConfigChange = true;
            }
        }

        private void refreshContentStyle()
        {
            foreach(TabPage page in tab_content.TabPages)
            {
                RichTextBox tb = page.Controls[0] as RichTextBox;
                tb.Font = contentFont;
                tb.BackColor = contentColor;
                tb.ForeColor = contentFontColor;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if(File.Exists("config.ini"))
            {
                IniFile ini = new IniFile("config.ini", Encoding.Default);
                contentFont = new Font(
                    ini.get("font", "family", "宋体"),  //family
                    ini.getFloat("font", "size", 12f),
                    (FontStyle)Enum.Parse(typeof(FontStyle), ini.get("font", "style", "Regular")),
                    GraphicsUnit.Point);  //fontstyle
                contentFontColor = Color.FromArgb(ini.getInt("font", "color", SystemColors.WindowText.ToArgb()));
                contentColor = Color.FromArgb(ini.getInt("font", "bgcolor", SystemColors.Window.ToArgb()));
                bookEncoding = Encoding.GetEncoding(ini.get("system", "encoding", Encoding.Default.ToString()));
                isConfigChange = false;
            }
            else
            {
                contentFont = RichTextBox.DefaultFont;
                contentFontColor = SystemColors.Window;
                contentColor = SystemColors.WindowText;
                bookEncoding = Encoding.Default;
                isConfigChange = true;
            }
            foreach (ToolStripItem item in m_encoding.DropDownItems)
                if (item is ToolStripMenuItem)
                {
                    ToolStripMenuItem menu=(ToolStripMenuItem)item;
                    if(menu.Text==bookEncoding.BodyName)
                    {
                        ((ToolStripMenuItem)item).Checked = true;
                        return;
                    }
                }
            m_encoding_default.Checked = true;
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (isConfigChange)
            {
                IniFile ini = new IniFile();
                ini.set("font", "family", contentFont.FontFamily.GetName(132));
                ini.set("font", "size", contentFont.SizeInPoints.ToString());
                ini.set("font", "style", contentFont.Style.ToString());
                ini.set("font", "color", contentFontColor.ToArgb().ToString());
                ini.set("font", "bgcolor", contentColor.ToArgb().ToString());
                ini.set("system", "encoding", bookEncoding.BodyName);
                ini.saveFile("config.ini");
            }
        }

        private void m_quit_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if(contentChangeList.Count>0)
            {
                if (MessageBox.Show("还有文件未保存，确认退出吗？", "确认", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
                    e.Cancel = true;
            }
        }

        private void savePage(TabPage page)
        {
            if (page != null && contentChangeList.Contains(page))
            {
                contentChangeList.Remove(page);
                page.Text = page.Text.Substring(0, page.Text.Length - 1);
                FileDesc fd = page.Tag as FileDesc;
                if (String.IsNullOrWhiteSpace(fd.textBox.Text))
                {
                    if (File.Exists(fd.filename + ".txt"))
                        File.Delete(fd.filename + ".txt");
                    if (File.Exists(fd.filename + ".rtf"))
                        File.Delete(fd.filename + ".rtf");
                }
                else
                {
                    if (fd.type == FileType.rtf)
                    {
                        fd.textBox.SaveFile(fd.filename + ".rtf");
                    }
                    else
                    {
                        fd.type = FileType.txt;
                        File.WriteAllText(fd.filename + ".txt", fd.textBox.Text, bookEncoding);
                    }
                }
            }
        }

        private void m_save_Click(object sender, EventArgs e)
        {
            savePage(tab_content.SelectedTab);
        }

        private void m_save_all_Click(object sender, EventArgs e)
        {
            foreach (TabPage page in tab_content.TabPages)
                savePage(page);
        }

        private void onTextBoxChange(object sender, EventArgs e)
        {
            if (eventOn)
            {
                FileDesc fd = ((RichTextBox)sender).Tag as FileDesc;
                if (contentChangeList.Add(fd.page))
                    fd.page.Text = fd.page.Text + "*";
            }
        }

        private void tv_charpter_DoubleClick(object sender, EventArgs e)
        {
            TreeNode node = tv_charpter.SelectedNode;
            if(node!=null)
            {
                FileDesc fd = node.Tag as FileDesc;
                if(fd.page==null)
                {
                    addContentPage(fd.node);
                }

            }
        }

        private void onEncodingChange(object sender, EventArgs e)
        {
            foreach(ToolStripItem  item in m_encoding.DropDownItems)
            {
                if(item is ToolStripMenuItem)
                {
                    ((ToolStripMenuItem)item).Checked = false;
                }
            }
            ToolStripMenuItem menu = (ToolStripMenuItem)sender;
            if(menu.Text=="系统缺省")
            {
                bookEncoding = Encoding.Default;
                isConfigChange = true;
            }
            else
            {
                bookEncoding = Encoding.GetEncoding(menu.Text);
                isConfigChange = true;
            }
            menu.Checked = true;
        }

        private void tab_content_DoubleClick(object sender, EventArgs e)
        {
            if(tab_content.SelectedTab!=null)
            {
                if (contentChangeList.Contains(tab_content.SelectedTab))
                    if (MessageBox.Show("该文档还未保存，确认关闭吗？", "确认", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
                        return;
                FileDesc fd = tab_content.SelectedTab.Tag as FileDesc;
                fd.page = null;
                contentChangeList.Remove(tab_content.SelectedTab);
                tab_content.TabPages.RemoveAt(tab_content.SelectedIndex);
            }
        }
        




    }
}
